home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Tele / Pete Johnson / FC LogScan 1.0.2<source>.cpt / FC LogScan.p < prev    next >
Encoding:
Text File  |  1992-03-04  |  27.9 KB  |  967 lines  |  [TEXT/PJMM]

  1. program FCLogScan;
  2.  
  3.     uses
  4.         Globals, TextUtils, Configure;
  5.  
  6.     const
  7.         SINGLEQUOTE = chr(39);
  8.         ENDLINE = chr(13);
  9.         kRecLimit = 20;
  10.         kSessLimit = 100;
  11.  
  12.     type
  13.         BaudSpeed = record
  14.                 Baud300, Baud1200, Baud2400, Baud4800, Baud9600, Baud14400, Baud19200, Baud38400: integer;
  15.             end;
  16.         NewU = array[1..1] of string[25];
  17.         NewUPtr = ^NewU;
  18.         NewUHdl = ^NewUPtr;
  19.         NameStuff = record
  20.                 Name: string[35];
  21.                 NameCount: integer;
  22.                 startTime, totalTime: longint;
  23.                 specialLine: boolean;
  24.             end;
  25.         callerIDs = array[1..1] of NameStuff;
  26.         callerPtr = ^callerIDs;
  27.         callerHdl = ^callerPtr;
  28.         hourArray = record
  29.                 sessNum: integer;
  30.                 thirdHours: array[0..71] of char;
  31.                 sessBegin, sessTotalTime: longint;
  32.                 isActive: boolean;
  33.             end;
  34.         timeUsed = array[1..1] of hourArray;
  35.         timePtr = ^timeUsed;
  36.         timeHdl = ^timePtr;
  37.  
  38.     var
  39.         myCallerHdl: callerHdl;
  40.         myTimeHdl: timeHdl;
  41.         NewUsers: NewUHdl;
  42.         BaudRates: BaudSpeed;
  43.         KnownSession: array[0..kSessLimit] of boolean;
  44.         session: array[1..kRecLimit] of integer;
  45.         CLineCount, GUICount, HowManyCallers, HowManySessions: integer;
  46.         StartHour, EndHour, newUserCount, BaudCount: integer;
  47.         currentLog, gSessString: str255;
  48.         usingAMPM, DoBaudReport: boolean;
  49.         logStartTime, logEndTime: longint;
  50.         runDialog: DialogPtr;
  51.         oldPort: GrafPtr;
  52.  
  53. {-----------------------------------------------------------------    }
  54.  
  55.     function MakeMonthString (monthNum: integer): str255;
  56.  
  57.     begin
  58.         case monthNum of
  59.             1: 
  60.                 MakeMonthString := 'Jan';
  61.             2: 
  62.                 MakeMonthString := 'Feb';
  63.             3: 
  64.                 MakeMonthString := 'Mar';
  65.             4: 
  66.                 MakeMonthString := 'Apr';
  67.             5: 
  68.                 MakeMonthString := 'May';
  69.             6: 
  70.                 MakeMonthString := 'Jun';
  71.             7: 
  72.                 MakeMonthString := 'Jul';
  73.             8: 
  74.                 MakeMonthString := 'Aug';
  75.             9: 
  76.                 MakeMonthString := 'Sep';
  77.             10: 
  78.                 MakeMonthString := 'Oct';
  79.             11: 
  80.                 MakeMonthString := 'Nov';
  81.             12: 
  82.                 MakeMonthString := 'Dec';
  83.             otherwise
  84.                 ;
  85.         end;
  86.     end;
  87.  
  88. {-----------------------------------------------------------------    }
  89.  
  90.     procedure AddNewSession (sessNum: integer; currTime: longint);
  91.  
  92.         var
  93.             newSize: longint;
  94.             counter: integer;
  95.             sessRec: hourArray;
  96.  
  97.     begin
  98.         KnownSession[sessNum] := true;
  99.         HowManySessions := succ(HowManySessions);
  100.         newSize := GetHandleSize(Handle(myTimeHdl)) + sizeOf(hourArray);
  101.         SetHandleSize(Handle(myTimeHdl), newSize);
  102.         if MemError <> NoErr then
  103.             begin
  104.                 SysBeep(6);
  105.                 ExitToShell
  106.             end;
  107.         sessRec.sessNum := sessNum;
  108.         for counter := 0 to 71 do
  109.             sessRec.thirdHours[counter] := NoCallSymbol;
  110.         sessRec.sessBegin := currTime;
  111.         sessRec.sessTotalTime := 0;
  112.         sessRec.isActive := true;
  113.         myTimeHdl^^[HowManySessions] := sessRec
  114.     end;
  115.  
  116. {-----------------------------------------------------------------    }
  117.  
  118.     function getTime (logString: str255): longint;
  119.  
  120. {    Returns number of seconds of time from log line                                    }
  121. {    [9/24/91 8:15:18 AM] Session 1.571 Start Sess 0 User 'Paul W Hampton'    }
  122.  
  123.         var
  124.             dateString, timeString, tempString, yearString, monthString, dayString, hourString, minuteString, secString: str255;
  125.             myDTR: DateTimeRec;
  126.             nowSecs: longint;
  127.  
  128.     begin
  129.         tempString := copy(logString, 2, pos(']', logString) - 2);    {get date & time without brackets}
  130.         dateString := copy(tempString, 1, pos(' ', tempString) - 1);    {just want the date}
  131.         timeString := copy(tempString, pos(' ', tempString) + 1, 255);    {just want the time}
  132.         monthString := copy(dateString, 1, pos('/', dateString) - 1);
  133.         dateString := copy(dateString, pos('/', dateString) + 1, 255);
  134.         dayString := copy(dateString, 1, pos('/', dateString) - 1);
  135.         yearString := copy(dateString, pos('/', dateString) + 1, 255);
  136.         hourString := copy(timeString, 1, pos(':', timeString) - 1);
  137.         timeString := copy(timeString, pos(':', timeString) + 1, 255);
  138.         minuteString := copy(timeString, 1, pos(':', timeString) - 1);
  139.         timeString := copy(timeString, pos(':', timeString) + 1, 255);
  140.         secString := copy(timeString, 1, pos(' ', timeString) - 1);
  141.  
  142.         with myDTR do
  143.             begin
  144.                 year := 1900 + GetValue(yearString);
  145.                 month := GetValue(monthString);
  146.                 day := GetValue(dayString);
  147.                 hour := GetValue(hourString);
  148.                 if (pos('PM', timeString) > 0) & (hour < 12) then
  149.                     hour := hour + 12;
  150.                 if (pos('AM', timeString) > 0) & (hour = 12) then
  151.                     hour := 0;
  152.                 minute := GetValue(minuteString);
  153.                 second := GetValue(secString);
  154.             end;
  155.         Date2Secs(myDTR, nowSecs);
  156.         getTime := nowSecs
  157.     end;
  158.  
  159. {-----------------------------------------------------------------    }
  160.  
  161.     procedure getStartTime (logString: str255);
  162.  
  163.         var
  164.             dateString, hourString: str255;
  165.  
  166.     begin
  167.         logStartTime := GetTime(logString);
  168.         dateString := copy(logString, 2, pos(']', logString) - 2);    {get date & time without brackets}
  169.         dateString := copy(dateString, pos(' ', dateString) + 1, 255);    {just want the time}
  170.         if (pos('AM', dateString) = 0) & (pos('PM', dateString) = 0) then
  171.             usingAMPM := false
  172.         else
  173.             usingAMPM := true;
  174.         hourString := copy(dateString, 1, pos(':', dateString) - 1);
  175.         if usingAMPM & (hourString = '12') & (pos('PM', dateString) = 0) then
  176.             hourString := '0';
  177.         StartHour := getValue(hourString)
  178.     end;
  179.  
  180. {-----------------------------------------------------------------    }
  181.  
  182.     function GetGraphPos (dateTimeString: str255): integer;
  183.  
  184. {    dateTimeString is of form 9/17/91 2:17:56 PM        }
  185.  
  186.         var
  187.             bonus: integer;
  188.             hourString, minuteString, tempString: str255;
  189.             totalMinutes, totalThirds: integer;
  190.  
  191.     begin
  192.         tempString := copy(dateTimeString, pos(' ', dateTimeString) + 1, 255);    {just want the time}
  193.         hourString := copy(tempString, 1, pos(':', tempString) - 1);
  194.         if usingAMPM & (pos('PM', tempString) > 0) & (GetValue(hourString) <> 12) then    {string is now 2:17:56 PM}
  195.             bonus := 12 * 60
  196.         else
  197.             bonus := 0;
  198.         if usingAMPM & (pos('AM', tempString) <> 0) & (hourString = '12') then
  199.             hourString := '0';
  200.         EndHour := getValue(hourString);
  201.         tempString := copy(tempString, pos(':', tempString) + 1, 255);
  202.         minuteString := copy(tempString, 1, pos(':', tempString) - 1);
  203.         totalMinutes := (60 * getValue(hourString)) + getValue(minuteString) + bonus;
  204.         totalThirds := totalMinutes div 20;
  205.  
  206.         if totalThirds > 71 then
  207.             totalThirds := 71;
  208.         GetGraphPos := totalThirds
  209.     end;
  210.  
  211. {-----------------------------------------------------------------    }
  212.  
  213.     function GetSessNum (lineString: str255): integer;
  214.  
  215.         var
  216.             mark: integer;
  217.             sessNum, currTime: longint;
  218.  
  219.     begin
  220.         currTime := GetTime(lineString);
  221.         mark := pos('Sess ', lineString);
  222.         mark := mark + 5;    {length of 'Sess '}
  223.         lineString := copy(lineString, mark, 255);
  224.         mark := 1;
  225.         while (lineString[mark] in ['0'..'9']) & (mark < length(lineString)) do
  226.             mark := succ(mark);
  227.         lineString := copy(lineString, 1, pred(mark));
  228.         StringToNum(lineString, sessNum);
  229.         if (HowManySessions = 0) | (not KnownSession[sessNum]) then
  230.             AddNewSession(sessNum, currTime);
  231.         GetSessNum := sessNum
  232.     end;
  233.  
  234. {-----------------------------------------------------------------    }
  235.  
  236.     procedure GetSessionFromLine (lineString: str255);
  237.  
  238. {    [9/24/91 8:15:18 AM] Session 1.571 Start Sess 0 User 'Paul W Hampton'    }
  239. {                                            - or -                                            }
  240. {    [9/17/91 2:17:56 PM] Command Line Session Start C-Sess 0 User 'DTOPS'    }
  241.  
  242.         var
  243.             count: integer;
  244.             sessNum, currentLogTime: longint;
  245.             dateTimeString, tempString: str255;
  246.             sessExists, sessStart: boolean;
  247.  
  248.     begin
  249.         sessNum := GetSessNum(lineString);
  250.         currentLogTime := GetTime(lineString);
  251.         if (pos(gSessStart, lineString) > 0) then
  252.             sessStart := true
  253.         else
  254.             sessStart := false;
  255.         dateTimeString := copy(lineString, 2, pos(']', lineString) - 2);    {get date & time without brackets}
  256.         for count := 1 to HowManySessions do
  257.             if myTimeHdl^^[count].sessNum = sessNum then
  258.                 begin
  259.                     if sessStart then
  260.                         myTimeHdl^^[count].sessBegin := currentLogTime;
  261.                     myTimeHdl^^[count].thirdHours[GetGraphPos(dateTimeString)] := CallSymbol;
  262.                     myTimeHdl^^[count].isActive := true;
  263.                     leave
  264.                 end;
  265.     end;
  266.  
  267. {-----------------------------------------------------------------    }
  268.  
  269.     procedure GetBaudFromLine (logLine: str255);
  270.  
  271. {    [10/11/91 10:11:13 PM] Session 1.600 Start @2400 baud Sess 0 User 'WParker'    }
  272.  
  273.         var
  274.             baudString: str255;
  275.             OKBaud: boolean;
  276.  
  277.     begin
  278.         if (pos('@', logLine) > 0) then
  279.             begin
  280.                 OKBaud := true;
  281.                 BaudCount := succ(BaudCount);
  282.                 baudString := copy(logLine, (succ(pos('@', logLine))), 255);
  283.                 baudString := copy(baudString, 1, (pred(pos(' ', baudString))));
  284.                 if (length(baudString) > 5) | (length(baudString) < 3) then
  285.                     baudString := '';
  286.                 case GetValue(baudString) of
  287.                     300: 
  288.                         BaudRates.Baud300 := succ(BaudRates.Baud300);
  289.                     1200: 
  290.                         BaudRates.Baud1200 := succ(BaudRates.Baud1200);
  291.                     2400: 
  292.                         BaudRates.Baud2400 := succ(BaudRates.Baud2400);
  293.                     4800: 
  294.                         BaudRates.Baud4800 := succ(BaudRates.Baud4800);
  295.                     9600: 
  296.                         BaudRates.Baud9600 := succ(BaudRates.Baud9600);
  297.                     14400: 
  298.                         BaudRates.Baud14400 := succ(BaudRates.Baud14400);
  299.                     19200: 
  300.                         BaudRates.Baud19200 := succ(BaudRates.Baud19200);
  301.                     38400: 
  302.                         BaudRates.Baud38400 := succ(BaudRates.Baud38400);
  303.                     otherwise
  304.                         begin
  305.                             OKBaud := false;
  306.                             BaudCount := pred(BaudCount);
  307.                         end;
  308.                 end        {    case    }
  309.             end;        {    if (pos('@', logLine) > 0)    }
  310.         if OKBaud then
  311.             DoBaudReport := true;
  312.     end;
  313.  
  314. {-----------------------------------------------------------------    }
  315.  
  316.     procedure GetNameFromLine (logString: str255; beginSess: boolean);
  317.  
  318. {    caller name is last string on the line, contained within 'single quotes' i.e.        }
  319. {    [9/24/91 8:15:18 AM] Session 1.571 Start Sess 0 User 'Paul W Hampton'    }
  320. {                                            - or -                                            }
  321. {    [9/17/91 2:17:56 PM] Command Line Session Start C-Sess 0 User 'DTOPS'    }
  322.  
  323.         var
  324.             count: integer;
  325.             newSize, currTime: longint;
  326.             alreadyExists: boolean;
  327.             nameString: str255;
  328.             currName: NameStuff;
  329.             SpecialCaller: boolean;
  330.  
  331.     begin
  332.         SpecialCaller := false;
  333.         if beginSess then
  334.             if (pos(gSessString, logString) > 0) then
  335.                 SpecialCaller := true;
  336.         nameString := copy(logString, 1, length(logString) - 1);    {trim last single quote}
  337.         while pos(SINGLEQUOTE, nameString) > 0 do
  338.             nameString := copy(nameString, succ(pos(SINGLEQUOTE, nameString)), 255);
  339.         alreadyExists := false;
  340.         currTime := GetTime(logString);
  341.         for count := 1 to HowManyCallers do
  342.             begin
  343.                 currName := myCallerHdl^^[count];
  344.                 if currName.Name = nameString then
  345.                     begin
  346.                         currName.NameCount := succ(currName.NameCount);
  347.                         if beginSess then
  348.                             begin
  349.                                 currName.startTime := currTime;
  350.                                 currName.specialLine := SpecialCaller;
  351.                             end
  352.                         else
  353.                             begin    {end of session}
  354.                                 if currName.startTime <> 0 then
  355.                                     currName.totalTime := currTime - currName.startTime + currName.totalTime
  356.                                 else
  357.                                     currName.totalTime := currTime - logStartTime + currName.totalTime;
  358.                                 currName.startTime := 0;
  359.                             end;
  360.                         alreadyExists := true;
  361.                         myCallerHdl^^[count] := currName;
  362.                         leave
  363.                     end;
  364.             end;
  365.         if not alreadyExists then
  366.             begin
  367.                 HowManyCallers := succ(HowManyCallers);
  368.                 newSize := sizeOf(callerIDs) + (HowManyCallers * sizeOf(NameStuff));
  369.                 SetHandleSize(Handle(myCallerHdl), newSize);
  370.                 MoveHHi(Handle(myCallerHdl));
  371.                 HLock(Handle(myCallerHdl));
  372.                 currName.Name := nameString;
  373.                 currName.NameCount := 1;
  374.                 currName.startTime := currTime;
  375.                 currName.totalTime := 0;
  376.                 currName.specialLine := SpecialCaller;
  377.                 myCallerHdl^^[HowManyCallers] := currName;
  378.                 HUnlock(Handle(myCallerHdl))
  379.             end
  380.     end;
  381.  
  382. {-----------------------------------------------------------------    }
  383.  
  384.     procedure addNewUser (logLine: str255);
  385.  
  386.  
  387. {    line reads     [10/1/91 9:41:39 AM] User Ronald a Luna auto-registered Sess 0        }
  388. {    gAutoRegister = ' auto-registered Sess '                                                }
  389.         var
  390.             NewSize: longint;
  391.             tempString: str255;
  392.  
  393.     begin
  394.         newUserCount := succ(newUserCount);
  395.         SetHandleSize(Handle(NewUsers), sizeOf(NewU) + (pred(newUserCount) * 26));    {26 = size of string[25]}
  396.         tempString := copy(logLine, (pos('User', logLine) + 5), 255);    {clip off User }
  397.         tempString := copy(tempString, 1, pred(pos(gAutoRegister, tempString)));
  398.         if length(tempString) > 25 then
  399.             tempString := copy(tempString, 1, 25);
  400.         NewUsers^^[newUserCount] := tempString;
  401.     end;
  402.  
  403. {-----------------------------------------------------------------    }
  404.  
  405.     procedure EndSession (lineString: str255);
  406.  
  407.         var
  408.             dateTimeString: str255;
  409.             ClosePos, sessNum, graphPos, counter: integer;
  410.             currentLogTime: longint;
  411.             timeRecord: hourArray;
  412.  
  413.     begin
  414.         dateTimeString := copy(lineString, 2, pos(']', lineString) - 2);    {get date & time without brackets}
  415.         ClosePos := GetGraphPos(dateTimeString);    {get session end time}
  416.         sessNum := GetSessNum(lineString);
  417.         graphPos := GetGraphPos(dateTimeString);
  418.         for counter := 1 to HowManySessions do
  419.             begin
  420.                 timeRecord := myTimeHdl^^[counter];
  421.                 if (timeRecord.sessNum = sessNum) & timeRecord.isActive then
  422.                     begin
  423.                         GetNameFromLine(lineString, false);    {false means end session}
  424.                         timeRecord.isActive := false;
  425.                         currentLogTime := GetTime(lineString);
  426.                         timeRecord.sessTotalTime := timeRecord.sessTotalTime + (currentLogTime - timeRecord.sessBegin);
  427.                         timeRecord.sessBegin := 0;
  428.                         while (timeRecord.thirdHours[graphPos] <> CallSymbol) & (graphPos >= (StartHour * 3)) do
  429.                             begin
  430.                                 timeRecord.thirdHours[graphPos] := CallSymbol;
  431.                                 graphPos := pred(graphPos)
  432.                             end;
  433.                         myTimeHdl^^[counter] := timeRecord;
  434.                         leave
  435.                     end    {    if timeRecord.sessNum = sessNum    }
  436.             end;
  437.     end;
  438.  
  439. {-----------------------------------------------------------------    }
  440.  
  441.     procedure Analyze (logLine: str255);
  442.  
  443.     begin
  444.         if pos('[', logLine) = 1 then
  445.             begin
  446.                 if StartHour < 0 then
  447.                     getStartTIme(logLine);
  448.                 logEndTime := GetTime(logLine);
  449.                 if (pos(gAutoRegister, logLine) > 0) then
  450.                     addNewUser(logLine);
  451.                 if (pos(gSessStart, logLine) > 0) then
  452.                     begin
  453.                         GetBaudFromLine(logLine);
  454.                         GetNameFromLine(logLine, true);    {true means begin session}
  455.                         GetSessionFromLine(logLine);
  456.                         if pos(gCommandLine, logLine) > 0 then
  457.                             CLineCount := succ(CLineCount)
  458.                         else
  459.                             GUICount := succ(GUICount)
  460.                     end
  461.                 else if (pos(gSessionEnd, logLine) > 0) then
  462.                     EndSession(logLine)
  463.             end
  464.     end;
  465.  
  466. {-----------------------------------------------------------------    }
  467.  
  468.     procedure Initialize;
  469.  
  470.         var
  471.             counter: integer;
  472.  
  473.     begin
  474.         StartHour := -1;
  475.         DoBaudReport := false;
  476.         myCallerHdl := callerHdl(newHandle(sizeOf(callerIDs)));
  477.         myTimeHdl := timeHdl(newHandle(0));
  478.         NewUsers := newUHdl(newHandle(sizeOf(NewU)));
  479.         BaudRates.Baud300 := 0;
  480.         BaudRates.Baud1200 := 0;
  481.         BaudRates.Baud2400 := 0;
  482.         BaudRates.Baud4800 := 0;
  483.         BaudRates.Baud9600 := 0;
  484.         BaudRates.Baud14400 := 0;
  485.         BaudRates.Baud19200 := 0;
  486.         BaudRates.Baud38400 := 0;
  487.         BaudCount := 0;
  488.         newUserCount := 0;
  489.         HowManySessions := 0;
  490.         HowManyCallers := 0;
  491.         CLineCount := 0;
  492.         GUICount := 0;
  493.         for counter := 1 to kRecLimit do
  494.             session[counter] := 0;
  495.         for counter := 0 to kSessLimit do
  496.             KnownSession[counter] := false
  497.     end;
  498.  
  499. {-----------------------------------------------------------------    }
  500.  
  501.     procedure CleanUp;
  502.  
  503.     begin
  504.         DisposHandle(Handle(myCallerHdl));
  505.         DisposHandle(Handle(myTimeHdl));
  506.         DisposHandle(Handle(NewUsers));
  507.     end;
  508.  
  509. {-----------------------------------------------------------------    }
  510.  
  511.     procedure sortTimeHandle (Start, Finish: integer);
  512.  
  513.         var
  514.             tempHourArray: hourArray;
  515.             Left, Right, StarterValue: integer;
  516.  
  517.     begin
  518.         Left := Start;
  519.         Right := Finish;
  520.         StarterValue := myTimeHdl^^[(Start + Finish) div 2].sessNum;    {    Pick a starter    }
  521.         repeat
  522.             while myTimeHdl^^[Left].sessNum < StarterValue do
  523.                 Left := Left + 1;    {    Find a bigger value on the left    }
  524.             while StarterValue < myTimeHdl^^[Right].sessNum do
  525.                 Right := Right - 1;    {    Find a smaller value on the right    }
  526.             if Left <= Right then
  527.                 begin    {If we haven't gone too far...    }
  528.                     tempHourArray := myTimeHdl^^[Left];
  529.                     myTimeHdl^^[Left] := myTimeHdl^^[Right];
  530.                     myTimeHdl^^[Right] := tempHourArray;
  531.                     Left := Left + 1;
  532.                     Right := Right - 1
  533.                 end;    {    then    }
  534.         until Right <= Left;
  535.         if Start < Right then
  536.             sortTimeHandle(Start, Right);
  537.         if Left < Finish then
  538.             sortTimeHandle(Left, Finish);
  539.     end;
  540.  
  541. {-----------------------------------------------------------------    }
  542.  
  543.     function MakeHMS (secTotal: longint): str255;
  544.  
  545.         var
  546.             hours, minutes, seconds: integer;
  547.             minuteString, secondsString: str255;
  548.  
  549.     begin
  550.         hours := secTotal div 3600;
  551.         secTotal := secTotal mod 3600;
  552.         minutes := secTotal div 60;
  553.         minuteString := StringOf(minutes : 1);
  554.         if length(minuteString) = 1 then
  555.             minuteString := concat('0', minuteString);
  556.         seconds := secTotal mod 60;
  557.         secondsString := StringOf(seconds : 1);
  558.         if length(secondsString) = 1 then
  559.             secondsString := concat('0', secondsString);
  560.         MakeHMS := concat(RPadString(StringOf(hours : 1), 2), ':', minuteString, ':', secondsString)
  561.     end;
  562.  
  563. {-----------------------------------------------------------------    }
  564.  
  565.     function MakeDateline (Secs: longint): str255;
  566.  
  567.         var
  568.             DTR: DateTimeRec;
  569.             tempString, timeString, AMPM, myDayOfWeek: str255;
  570.  
  571.     begin
  572.         Secs2Date(Secs, DTR);
  573.         if DTR.minute < 10 then
  574.             tempString := concat('0', stringOf(DTR.minute : 1))
  575.         else
  576.             tempString := stringOf(DTR.minute : 1);
  577.         if usingAMPM then
  578.             begin
  579.                 AMPM := 'AM';
  580.                 if DTR.hour > 12 then
  581.                     begin
  582.                         DTR.hour := DTR.hour - 12;
  583.                         AMPM := 'PM';
  584.                     end
  585.                 else if DTR.hour = 12 then
  586.                     AMPM := 'PM';
  587.                 timeString := concat(stringOf(DTR.hour : 1), ':', tempString, ' ', AMPM);
  588.             end
  589.         else
  590.             timeString := concat(stringOf(DTR.hour : 1), ':', stringOf(DTR.minute : 1));
  591.         case DTR.dayOfWeek of
  592.             1: 
  593.                 myDayOfWeek := 'Sunday';
  594.             2: 
  595.                 myDayOfWeek := 'Monday';
  596.             3: 
  597.                 myDayOfWeek := 'Tuesday';
  598.             4: 
  599.                 myDayOfWeek := 'Wednesday';
  600.             5: 
  601.                 myDayOfWeek := 'Thursday';
  602.             6: 
  603.                 myDayOfWeek := 'Friday';
  604.             7: 
  605.                 myDayOfWeek := 'Saturday';
  606.             otherwise
  607.                 myDayOfWeek := '';
  608.         end;
  609.         tempString := concat(timeString, ' ', myDayOfWeek, ' ', stringOf(DTR.month : 1), '/', stringOf(DTR.day : 1), '/', stringOf(DTR.year mod 100 : 1));
  610.         MakeDateline := tempString
  611.     end;
  612.  
  613. {-----------------------------------------------------------------    }
  614.  
  615.     function PrintUse (totalSecs: longint; mult: integer): str255;
  616.  
  617. {    Forms line with total time and percentage of use. Called with multiplier for how many 24-hour days    }
  618.  
  619.         const
  620.             kSecsInDay = longint(24 * 6 * 6);    {since we're going to multiply by 100 to get percentage, do it here by division    }
  621.  
  622.     begin
  623.         if mult > 0 then
  624.             PrintUse := concat(' ', TimeUsedTitle, ' ', MakeHMS(totalSecs), ' --', RPadString(stringOf(totalSecs div (mult * kSecsInDay) : 1), 3), '%')
  625.     end;
  626.  
  627. {-----------------------------------------------------------------    }
  628.  
  629.     function MakeBaudLine (BaudString: str255; BaudRate: integer): str255;
  630.  
  631.         var
  632.             baudReal: real;
  633.             baudInt: integer;
  634.             tempString: str255;
  635.  
  636.     begin
  637.         tempString := concat(LPadString(BaudString, 6), '--', RPadString(stringOf(BaudRate : 1), 4));
  638.         baudReal := 100 * (BaudRate / BaudCount);
  639.         baudInt := trunc(baudReal + 0.5);
  640.         MakeBaudLine := concat(tempString, RPadString(concat(stringOf(baudInt : 1), '%'), 6))
  641.     end;
  642.  
  643. {-----------------------------------------------------------------    }
  644.  
  645.     procedure WriteReport (reportRef: integer; doBriefFile: boolean);
  646.  
  647.         var
  648.             count, i, OKSessCount, sequenceCount, howManyDays: integer;
  649.             Err: OSErr;
  650.             OKSession: boolean;
  651.             curName: NameStuff;
  652.             sessRec: hourArray;
  653.             sessCumeTime: longint;
  654.             briefRef: integer;
  655.             hourString, specialSession, sessMark: str255;
  656.  
  657. {---------------------------------}
  658.  
  659.         function Wr2 (ref1, ref2: integer; theString: str255): OSErr;
  660.  
  661.             var
  662.                 theErr: OSErr;
  663.  
  664.         begin
  665.             theErr := Wr(ref1, theString);
  666.             if doBriefFile & (theErr = NoErr) then
  667.                 theErr := Wr(ref2, theString);
  668.             Wr2 := theErr
  669.         end;
  670.  
  671. {---------------------------------}
  672.  
  673.         function WrLn2 (ref1, ref2: integer; theString: str255): OSErr;
  674.  
  675.             var
  676.                 theErr: OSErr;
  677.  
  678.         begin
  679.             theErr := WrLn(ref1, theString);
  680.             if doBriefFile & (theErr = NoErr) then
  681.                 theErr := WrLn(ref2, theString);
  682.             WrLn2 := theErr
  683.         end;
  684.  
  685. {---------------------------------}
  686.  
  687.     begin
  688.         sessCumeTime := 0;
  689.         howManyDays := 0;
  690.  
  691.         if doBriefFile & (Defaults.BriefPath <> '') & (Defaults.BriefName <> '') then
  692.             begin
  693.                 err := FSDelete(concat(Defaults.BriefPath, Defaults.BriefName), vRefNum);
  694.                 err := Create(concat(Defaults.BriefPath, Defaults.BriefName), vRefNum, Defaults.Creator, 'TEXT');
  695.                 err := FSOpen(concat(Defaults.BriefPath, Defaults.BriefName), vRefNum, briefRef);
  696.                 if err <> NoErr then
  697.                     doBriefFile := false
  698.             end
  699.         else
  700.             doBriefFile := false;
  701.  
  702.         if TitleString[length(TitleString)] <> ENDLINE then
  703.             TitleString := concat(TitleString, ENDLINE);
  704.         TitleString := ReplaceInString(TitleString, '^0', MakeDateline(logStartTime));
  705.         TitleString := ReplaceInString(TitleString, '^1', MakeDateline(logEndTime));
  706.         Err := Wr2(reportRef, briefRef, TitleString);
  707.  
  708.         if SummaryString[length(SummaryString)] <> ENDLINE then
  709.             SummaryString := concat(SummaryString, ENDLINE);
  710.         SummaryString := ReplaceInString(SummaryString, '^0', stringOf(GUICount : 1));
  711.         SummaryString := ReplaceInString(SummaryString, '^1', stringOf(CLineCount : 1));
  712.         SummaryString := ReplaceInString(SummaryString, '^2', stringOf(GUICount + CLineCount : 1));
  713.         Err := WrLn2(reportRef, briefRef, SummaryString);
  714.  
  715.         if LegendString[length(LegendString)] <> ENDLINE then
  716.             LegendString := concat(LegendString, ENDLINE);
  717.         Err := WrLn2(reportRef, briefRef, LegendString);
  718.  
  719.         hourString := '';
  720.         for count := StartHour to 23 do
  721.             if count < 10 then
  722.                 hourString := concat(hourString, stringOf(count : 1), '  ')
  723.             else
  724.                 hourString := concat(hourString, stringOf(count : 1), ' ');
  725.         for count := 0 to pred(StartHour) do
  726.             if count < 10 then
  727.                 hourString := concat(hourString, stringOf(count : 1), '  ')
  728.             else
  729.                 hourString := concat(hourString, stringOf(count : 1), ' ');
  730.         Err := WrLn2(reportRef, briefRef, hourString);
  731.  
  732.         MoveHHi(Handle(myTimeHdl));
  733.         HLock(Handle(myTimeHdl));
  734.         sortTimeHandle(1, HowManySessions);
  735.         for count := 1 to HowManySessions do
  736.             begin
  737.                 OKSession := true;
  738.                 sessRec := myTimeHdl^^[count];
  739.                 for OKSessCount := 1 to HowManyOmits do
  740.                     if sessRec.sessNum = Defaults.IgnoreSess[OKSessCount] then
  741.                         begin
  742.                             OKSession := false;
  743.                             leave
  744.                         end;
  745.                 if OKSession then
  746.                     begin
  747.                         for i := (StartHour * 3) to 71 do
  748.                             Err := Wr2(reportRef, briefRef, sessRec.thirdHours[i]);
  749.                         for i := 0 to pred((StartHour) * 3) do
  750.                             Err := Wr2(reportRef, briefRef, sessRec.thirdHours[i]);
  751.                         Err := WrLn2(reportRef, briefRef, '');
  752.                     end
  753.             end;
  754.         for count := 1 to HowManySessions do
  755.             begin
  756.                 OKSession := true;
  757.                 sessRec := myTimeHdl^^[count];
  758.                 for OKSessCount := 1 to HowManyOmits do
  759.                     if sessRec.sessNum = Defaults.IgnoreSess[OKSessCount] then
  760.                         begin
  761.                             OKSession := false;
  762.                             leave
  763.                         end;
  764.                 if OKSession then
  765.                     begin
  766.                         Err := WrLn2(reportRef, briefRef, concat(LineTitle, ' ', StringOf(count : 1), PrintUse(sessRec.sessTotalTime, 1)));
  767.                         sessCumeTime := sessCumeTime + sessRec.sessTotalTime;
  768.                         howManyDays := succ(howManyDays);
  769.                     end;
  770.             end;        {for count := 1 to HowManySessions}
  771.         Err := WrLn2(reportRef, briefRef, concat(TotalTitle, ' ', PrintUse(sessCumeTime, howManyDays), ENDLINE));
  772.  
  773.         if DoBaudReport then
  774.             begin
  775.                 Err := WrLn2(reportRef, briefRef, ConnectionSpeedsTitle);
  776.                 if (BaudRates.Baud300 > 0) then
  777.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('300', BaudRates.Baud300));
  778.                 if (BaudRates.Baud1200 > 0) then
  779.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('1200', BaudRates.Baud1200));
  780.                 if (BaudRates.Baud2400 > 0) then
  781.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('2400', BaudRates.Baud2400));
  782.                 if (BaudRates.Baud4800 > 0) then
  783.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('4800', BaudRates.Baud4800));
  784.                 if (BaudRates.Baud9600 > 0) then
  785.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('9600', BaudRates.Baud9600));
  786.                 if (BaudRates.Baud14400 > 0) then
  787.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('14400', BaudRates.Baud14400));
  788.                 if (BaudRates.Baud19200 > 0) then
  789.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('19200', BaudRates.Baud19200));
  790.                 if (BaudRates.Baud38400 > 0) then
  791.                     Err := WrLn2(reportRef, briefRef, MakeBaudLine('38400', BaudRates.Baud38400));
  792.                 Err := WrLn(reportRef, '');
  793.             end;    {if DoBaudReport    }
  794.         if doBriefFile then
  795.             err := FSClose(briefRef);
  796.  
  797.         specialSession := concat('[', StringOf(Defaults.SpecialSess : 0), ']');
  798.  
  799.         if newUserCount > 0 then
  800.             begin
  801.                 Err := WrLn(reportRef, RegistrationsTitle);
  802.                 HLock(Handle(NewUsers));
  803.                 for count := 1 to newUserCount do
  804.                     Err := WrLn(reportRef, NewUsers^^[count]);
  805.                 HUnlock(Handle(NewUsers));
  806.                 Err := WrLn(reportRef, '');
  807.             end;
  808.         Err := WrLn(reportRef, NameCallsTimeTitle);
  809.         for count := 1 to HowManyCallers do
  810.             begin
  811.                 curName := myCallerHdl^^[count];
  812.                 if curName.specialLine then
  813.                     sessMark := specialSession
  814.                 else
  815.                     sessMark := '    ';
  816.                 Err := WrLn(reportRef, concat(LPadString(curName.Name, 24), RPadString(stringOf(curName.NameCount : 1), 6), RPadString(stringOf((curName.totalTime + 30) div 60 : 1), 6), RPadString(sessMark, 6)))
  817.             end;
  818.         HUnlock(Handle(myTimeHdl))
  819.     end;
  820.  
  821. {-----------------------------------------------------------------    }
  822.  
  823.     procedure ProcessFile (fileName: str255; readRef, vRef: integer; doBriefFile: boolean);
  824.  
  825.         var
  826.             err: OSErr;
  827.             logLine: str255;
  828.             reportRef: integer;
  829.  
  830.     begin
  831.         Initialize;
  832.         Err := FSDelete(fileName, vRef);
  833.         Err := Create(fileName, vRef, Defaults.Creator, 'TEXT');
  834.         if Err = NoErr then
  835.             begin
  836.                 Err := FSOpen(fileName, vRef, reportRef);
  837.                 while not AtEOF(readRef) do
  838.                     begin
  839.                         Err := ReadALine(readRef, logLine);
  840.                         Analyze(logLine);
  841.                     end;
  842.                 WriteReport(reportRef, Defaults.DoBriefRept);
  843.                 Err := FSClose(reportRef);
  844.             end;
  845.         CleanUp
  846.     end;
  847.  
  848. {-----------------------------------------------------------------    }
  849.  
  850.     procedure ShowRunDialog;
  851.  
  852.     begin
  853.         SetCursor(GetCursor(watchCursor)^^);
  854.         GetPort(oldPort);
  855.         runDialog := GetNewDialog(501, nil, POINTER(-1));
  856.         SetPort(runDialog);
  857.         DrawDialog(runDialog);
  858.     end;
  859.  
  860. {-----------------------------------------------------------------    }
  861.  
  862.     procedure KillRunDialog;
  863.  
  864.     begin
  865.         DisposDialog(runDialog);
  866.         SetPort(oldPort);
  867.         InitCursor;
  868.     end;
  869.  
  870. {-----------------------------------------------------------------    }
  871.  
  872.     procedure ScanFiles;
  873.  
  874.         var
  875.             where: point;
  876.             reply: SFReply;
  877.             typeList: SFTypeList;
  878.             readRef, reportRef: integer;
  879.             Err: OSErr;
  880.             logLine: str255;
  881.             keepLooping: boolean;
  882.             dirID: longint;
  883.  
  884.     begin
  885.         keepLooping := true;
  886.         where.v := 20;
  887.         where.h := 20;
  888.         typeList[0] := 'TEXT';
  889.         while keepLooping = true do
  890.             begin
  891.                 SFGetFile(where, '', nil, 1, typeList, nil, reply);
  892.                 if reply.good then
  893.                     begin
  894.                         currentLog := reply.fName;
  895.                         Err := FSOpen(currentLog, reply.vRefNum, readRef);
  896.                         if (Err = NoErr) then
  897.                             begin
  898.                                 SFPutFile(where, 'Please name report', concat(currentLog, ' report'), nil, reply);
  899.                                 if reply.good then
  900.                                     begin
  901.                                         ShowRunDialog;
  902.                                         ProcessFile(reply.fName, readRef, reply.vRefNum, false);
  903.                                         KillRunDialog
  904.                                     end;
  905.                             end;
  906.                         Err := FSClose(readRef);
  907.                     end
  908.                 else
  909.                     keepLooping := false
  910.             end
  911.     end;
  912.  
  913. {-----------------------------------------------------------------    }
  914.  
  915.     procedure AutoReport;
  916.  
  917.         const
  918.             daySecs = 86400;
  919.  
  920.         var
  921.             Err: OSErr;
  922.             fName: str255;
  923.             dirID, secs: longint;
  924.             readRef: integer;
  925.             DTR: DateTimeRec;
  926.  
  927.     begin
  928.         Initialize;
  929.         GetDateTime(secs);
  930.         secs := secs - daySecs;
  931.         Secs2Date(secs, DTR);
  932.         fName := concat(MakeMonthString(DTR.month), stringOf(DTR.day : 1), '/', stringOf(DTR.year : 1));
  933.         Err := HOpen(vRefNum, dirID, concat(Defaults.FCLogPath, fName), fsRdPerm, readRef);
  934.         if (Err = NoErr) then
  935.             ProcessFile(concat(Defaults.FCLogPath, fName, ' report'), readRef, vRefNum, true);
  936.         Err := FSClose(readRef);
  937.         CleanUp
  938.     end;
  939.  
  940. {-----------------------------------------------------------------    }
  941.  
  942.     var
  943.         err: OSErr;
  944.         dirID: longint;
  945.         tempSettings: Settings;
  946.  
  947. begin
  948.     MaxApplZone;
  949.     InitCursor;
  950.     err := HGetVol(nil, vRefNum, dirID);
  951.     ReadDefaults;
  952.     gSessString := concat('Sess ', stringOf(Defaults.SpecialSess : 0));
  953.     if Button then
  954.         begin
  955.             tempSettings := Defaults;
  956.             if Configure(tempSettings) then
  957.                 WriteResources(tempSettings)
  958.         end
  959.     else if Defaults.Automatic then
  960.         begin
  961.             ShowRunDialog;
  962.             AutoReport;
  963.             KillRunDialog;
  964.         end
  965.     else
  966.         ScanFiles
  967. end.